package org.mm.proxycache;

import org.apache.mina.common.IoFilterAdapter;
import org.apache.mina.common.IoSession;
import org.mm.proxycache.ConnectionManager.ConnectionCallback;
import org.mm.proxycache.http.HttpMethod;
import org.mm.proxycache.http.HttpRequest;
import org.mm.proxycache.http.HttpUrl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.inject.Inject;
import com.google.inject.Provider;

public class ProxyClientHttpsFilter extends IoFilterAdapter
{

    private static Logger log = LoggerFactory.getLogger( ProxyClientHttpsFilter.class );

    @Inject
    private Provider<ConnectionManager> connectionManagerProvider;

    /*
     * (non-Javadoc)
     * 
     * @see org.apache.mina.common.IoFilterAdapter#messageReceived(org.apache.mina.common.IoFilter.NextFilter,
     *      org.apache.mina.common.IoSession, java.lang.Object)
     */
    @Override
    public void messageReceived( NextFilter nextFilter, final IoSession clientSession,
            Object message ) throws Exception
    {

        if ( !(message instanceof HttpRequest)
                || ((HttpRequest) message).method() != HttpMethod.CONNECT )
        {
            nextFilter.messageReceived( clientSession, message );
            return;
        }

        final HttpRequest request = (HttpRequest) message;

        log.debug( "HTTPS connection to {}", request.url() );

        // CONNECT URL will be in the form "host:port"
        final HttpUrl url = request.url();

        connectionManagerProvider.get().getConnection( url.host(), url.port(), clientSession,
                new ConnectionCallback() {

                    public void done( IoSession serverSession )
                    {
                        clientSession.setAttribute( HttpsMarker, Boolean.TRUE );
                        serverSession.setAttribute( HttpsMarker, Boolean.TRUE );
                        serverSession.setAttribute( HttpsPairConnection, clientSession );
                        clientSession.setAttribute( HttpsPairConnection, serverSession );

                        clientSession.write( HttpResponses.getHttpsConnectedResponse() );
                    }

                    public void error()
                    {
                        log.warn( "Error connecting to  {}:{}", url.host(), url.port() );
                        clientSession.write( HttpResponses.getNameErrorResponse() );
                        clientSession.closeOnFlush();
                    }

                } );
    }

    public static final String HttpsMarker = "ProxyClientHttpsFilter-HttpsMarker";

    public static final String HttpsPairConnection = "ProxyClientHttpsFilter-HttpsMarker";
}
